import java.awt._
import java.awt.event._


import java.awt.BorderLayout
import java.awt.Button
import java.awt.FlowLayout
import java.awt.Frame
import java.awt.Panel
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.TextEvent
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent

import fractal._
import util._

object FracgenUI extends Frame("Fractal Image Generator (using Concurrency)")
{
	val fg = FractalGenerator
	val Real = new TextField("    ")
	val Img = new TextField("    ")
	val SetParam = new Button("Set")

	val timeForCalcLabel = new Label
	val percentCompleteLabel = new Label
	var r:Double = 0.0
	var i:Double = 0.0
	var mouseEventFlag:Int = 3;
	val fi = FractalImage;
	var timeForCalc:String = " ";


	displayToolbars();
	displayFI();

	val imageSize = fi.getPreferredSize()
	setSize(imageSize.width+400,imageSize.height+100)
	addWindowListener(new WindowAdapter
	{ 
		override def windowClosing(e: WindowEvent): Unit =
		{ 
			closeWindow()
		} 
	})

	def main(args: Array[String]): Unit = 
	{
		FracgenUI.setVisible(true)
	}
	
	def closeWindow(): Unit =
	{ 
		setVisible(false)
		dispose()
		exit()
	}

	
	override def repaint(): Unit =
	{
		val t = new Thread(keepRefreshing)
		t.start()

		val calcTime = fg.generate()
		timeForCalc = (calcTime.toString().concat(" miliseconds for calculation"))
		timeForCalcLabel.setText(timeForCalc)
		timeForCalcLabel.repaint()
		t.interrupt()
		
	        val percentComplete = fg.getPercentageComplete()
        	percentCompleteLabel.setText(percentComplete.toString().concat("% completed"))
        	percentCompleteLabel.repaint()

		fi.repaint()
	}

	object keepRefreshing extends Runnable
	{
		val fi = FractalImage
		val percentComplete:Int = 0

		def run(): Unit =
		{
			try {
		            while(true)
		            {
		                 Thread.sleep(10)
		                 val percentComplete = fg.getPercentageComplete()
		                 percentCompleteLabel.setText(percentComplete.toString().concat("% completed"))
		                 percentCompleteLabel.repaint()
		            }
		        } catch {
				case e: Exception => e
      	
		        }
		}
	}

	def saveImageAs(): Unit =
	{
		val fd = new FileDialog(this, "Save Image As...", FileDialog.SAVE)
		fd.setFile("*.png")
	        fd.setDirectory(System.getProperty("user.home"))
        	fd.setVisible(true)
	        val fullpath = fd.getDirectory() + fd.getFile()
        	fd.dispose()
	        fg.saveImage(fullpath)
	}

	def saveParameters(): Unit = 
	{
		val fd = new FileDialog(this, "Save Parameter file", FileDialog.SAVE)
		fd.setFile("*.txt")
	        fd.setDirectory(System.getProperty("user.home"))
	        fd.setVisible(true)
	        val fullpath = fd.getDirectory() + fd.getFile()
	        fd.dispose()
	        fg.saveParameters(fullpath)
	}

	def setParameters(): Unit =
	{
		val f = new Julia(new Complex(r,i))
		fg.setFractal(f)
		val cp = fg.getComplexPlane()
		cp.reset();
		repaint();
	}

	def displayFI(): Unit =
	{
		val cp = fg.getComplexPlane()
		
		fi.addMouseListener(new MouseAdapter() {
			override def mouseClicked(e:MouseEvent): Unit =
			{
				val cp = fg.getComplexPlane();
				if (e.getButton() == MouseEvent.BUTTON1)
				{
					cp.setCenter(e.getX(), e.getY())
					if (mouseEventFlag==1) // Zoom In
					{
						cp.setScale(cp.getRealAxisScale()/2, cp.getImaginaryAxisScale()/2)
					}
					else if (mouseEventFlag==2) // Zoom Out
					{
						cp.setScale(cp.getRealAxisScale()*2, cp.getImaginaryAxisScale()*2)
					}
					repaint()
				}
			}
		})
		repaint()
		add("Center",fi)

	}

	def displayToolbars(): Unit = 
	{
		val topTListener = new ActionListener {
	        def actionPerformed(ae:ActionEvent): Unit =
		{
	        	val item:String = ae.getActionCommand()
	        	if (item.equals("Reset"))
			{
	        		val cp = fg.getComplexPlane()
	        		cp.reset()
	        		repaint()
	        	}
	        	else if (item.equals("Save Image"))
	        		saveImageAs()
	        	else if (item.equals("Save Parameters"))
	        		saveParameters()
	        }
	      }
	      
	      val l = new TextListener
	      {
			
			def textValueChanged(e:TextEvent): Unit =
			{
				if(e.getSource() == Real)
				{
					r = Real.getText().toDouble
				}
				else
				{
					i = Img.getText().toDouble
				}
			}
		}
	    
	    val zoomChoiceListener = new ItemListener {
	    	def itemStateChanged(e:ItemEvent): Unit =
		{
	    		val zoomChoice = e.getSource().asInstanceOf[Checkbox]
	    		val result = zoomChoice.getLabel()
	    		if (result.equals("Zoom Out"))
	    			mouseEventFlag = 2
	    		else if (result.equals("Zoom In"))
	    			mouseEventFlag = 1
	    		else if (result.equals("Scroll"))
	    			mouseEventFlag = 3
	    	}
	    }
	    
	    val fractalChoiceListener = new ItemListener {
	    	def itemStateChanged(e:ItemEvent): Unit =
	    	{
	    		val fractalChoice = e.getSource().asInstanceOf[Choice]
	    		val result = fractalChoice.getSelectedIndex()
    			Real.setEnabled(false)
    			Img.setEnabled(false)
    			SetParam.setEnabled(false)
	    		if(result == 0)
	    		{
	        		val f = new Mandelbrot()
	        		fg.setFractal(f)
	    			val cp = fg.getComplexPlane()
	    			cp.reset()
	    			repaint()
	    		}
	    		else if(result == 1)
	    		{
	    			//Fractal f = new Julia(new Complex(-0.835,-0.2321));
	    			//Fractal f = new Julia(new Complex(0.285,0.0));
	    			//Fractal f = new Julia(new Complex(0.285,0.01));
	    			//Fractal f = new Julia(new Complex(-0.70176,-0.3842));
	    			//Fractal f = new Julia(new Complex(-0.8,0.156));
	    			val f = new Julia(new Complex(-0.8,0.156))
	    			Real.setText("-0.8")
	    			Img.setText("0.156")
	    			//Fractal f = new Julia(new Complex(0.45,0.1428));
	    			//Fractal f = new Julia(new Complex(0.777,0.012));
	    			fg.setFractal(f)
	    			val cp = fg.getComplexPlane()
	    			cp.reset()
        			repaint()
        			Real.setEnabled(true)
        			Img.setEnabled(true)
        			SetParam.setEnabled(true)
	    		}
	    		else if(result == 2)
	    		{
	        		val f = new BurningShip()
	        		fg.setFractal(f)
	    			val cp = fg.getComplexPlane()
	    			cp.reset()
	    			repaint()
	    		}
	    	}
	    }
	    val numThreadChoiceListener = new ItemListener {
	    	def itemStateChanged(e:ItemEvent): Unit =
	    	{
	    		val numThreadChoice = e.getSource().asInstanceOf[Choice]
	    		val result = numThreadChoice.getSelectedIndex()+1
	    		if (result>0 && result <17)
	    			fg.setNumActors(result)
	    	}
	    }
    
	    val topToolbar = new Panel
	    topToolbar.setLayout(new FlowLayout(FlowLayout.LEFT))

	    val fractalChoice = new Choice()
	    fractalChoice.add("Mandelbrot Set")
	    fractalChoice.add("Julia Set")
	    fractalChoice.add("Burning Ship Fractal")
	    fractalChoice.addItemListener(fractalChoiceListener)
	    topToolbar.add(fractalChoice)

/*	    topToolbar.add(Real)
	    topToolbar.add(Img)
	    topToolbar.add(SetParam)
	    Real.addTextListener(l)
	    Img.addTextListener(l)
	    SetParam.addActionListener(topTListener)
	    Real.setEnabled(false)
	    Img.setEnabled(false)
	    SetParam.setEnabled(false)
	    Real.setBounds(getX(), getY(), 200, 200) */
	    
	    val resetButton = new Button("Reset")
	    resetButton.addActionListener(topTListener)
	    topToolbar.add(resetButton)
	    
	    val zoomGroup = new CheckboxGroup()
	    val zoomInChkBox = new Checkbox("Zoom In",zoomGroup,false)
	    val zoomOutChkBox = new Checkbox("Zoom Out",zoomGroup,false)
	    val scrollChkBox = new Checkbox("Scroll",zoomGroup,true)
	    zoomInChkBox.addItemListener(zoomChoiceListener)
	    zoomOutChkBox.addItemListener(zoomChoiceListener)
	    scrollChkBox.addItemListener(zoomChoiceListener)
	    topToolbar.add(zoomInChkBox)
	    topToolbar.add(zoomOutChkBox)
	    topToolbar.add(scrollChkBox)
	    
	    val saveImageButton = new Button("Save Image")
	    saveImageButton.addActionListener(topTListener)
	    topToolbar.add(saveImageButton)
	    
	    val saveParaButton = new Button("Save Parameters")
	    saveParaButton.addActionListener(topTListener)
	    topToolbar.add(saveParaButton)

	    val numThreadChoice = new Choice()
	    for (tempCounter <- 1 until 16)
	    {
	    	if(tempCounter==1)
	    		numThreadChoice.add((Integer.toString(tempCounter))+" Actor")
	    	else
	    		numThreadChoice.add((Integer.toString(tempCounter))+" Actors")
	    }
	    numThreadChoice.addItemListener(numThreadChoiceListener)
	    numThreadChoice.select("1")
	    topToolbar.add(numThreadChoice)
	    
	    add(topToolbar, BorderLayout.NORTH)

	    
//		Right Toolbar
		val rightTListener = new ActionListener {
	        def actionPerformed(ae:ActionEvent): Unit =
			{
	        		val item = ae.getActionCommand()
	        		if (item.equals("Set"))
	        			setParameters()
		        }
		}

	    val rightToolbar = new Panel()
	    rightToolbar.setLayout(new FlowLayout(FlowLayout.CENTER))
	    rightToolbar.add(new Label("Real"))
	    rightToolbar.add(Real)
	    rightToolbar.add(new Label("Img"))
	    rightToolbar.add(Img)
	    rightToolbar.add(SetParam)
	    Real.addTextListener(l)
	    Img.addTextListener(l)
	    SetParam.addActionListener(rightTListener)
	    Real.setEnabled(false)
	    Img.setEnabled(false)
	    SetParam.setEnabled(false)
	    
	    val BWorColorChkBoxListener = new ItemListener {
	    	def itemStateChanged(e:ItemEvent): Unit =
		{
	    		val BWorColorChkBox = e.getSource().asInstanceOf[Checkbox]
	    		val result = BWorColorChkBox.getLabel()
	    		if (result.equals("B&W"))
	    		{
	    			fg.makeBW
	    			repaint()
	    		}
	    		else if (result.equals("Color"))
	    		{
	    			fg.makeColor
	    			repaint()
	    		}
	    	}
	    }
	    val colorORbwGroup = new CheckboxGroup()
	    val BWChkBox = new Checkbox("B&W",colorORbwGroup,true)
	    val colorChkBox = new Checkbox("Color",colorORbwGroup,false)
	    BWChkBox.addItemListener(BWorColorChkBoxListener)
	    colorChkBox.addItemListener(BWorColorChkBoxListener)
	    rightToolbar.add(BWChkBox)
	    rightToolbar.add(colorChkBox)
	    
	    add(rightToolbar, BorderLayout.EAST)
	    
	    	    
	    
//		Bottom toolbar
	    val bottomToolbar = new Panel()
	    bottomToolbar.setLayout(new FlowLayout(FlowLayout.LEFT))
	    bottomToolbar.add(timeForCalcLabel)
	    bottomToolbar.add(percentCompleteLabel)
	    add(bottomToolbar, BorderLayout.SOUTH)
	}

}
